package org.clockworkmages.games.anno1186.dao;

import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class SerializationUtil {

	public static String serializeGameData(GameObjectsList gameObjects,
			boolean prettyPrint) {
		String serialized = serialize(gameObjects, prettyPrint);

		// TODO: ugly workarounds for JAXB's marshalling of default values.
		// There must be some beter way to do that...
		String[] defaults = new String[] { " addToStack=\"false\"", //
				" goBack=\"false\"", //
				" probability=\"0\"", //
				" clearScreen=\"true\"", //
				" consumesCombatAction=\"false\"", //
				" textfield=\"false\"", //
				" or=\"false\"", //
		};
		for (String s : defaults) {
			serialized = serialized.replace(s, "");
		}

		// clean up empty lines
		// .replaceAll("(?m)^[ \t]*\r?\n", "");

		return serialized;

	}

	public static String serialize(Object o, boolean prettyPrint) {
		try {
			StringWriter writer = new StringWriter();

			JAXBContext context = JAXBContext.newInstance(o.getClass());
			Marshaller marshaller = context.createMarshaller();
			if (prettyPrint) {
				marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
			}
			marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "");
			marshaller.marshal(o, writer);
			String serialized = writer.toString();

			return serialized;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	public static GameObjectsList deserializeGameData(String serializedString) {

		// TODO: ugly workaround for JAXB's ugly marshalling
		// serializedString = serializedString
		// .replace("<option>", "<option xsi:type=\"genericOption\">")
		// .replace(
		// "<gameObjects>",
		// "<gameObjects xsi:schemaLocation=\"\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");

		Reader reader = new StringReader(serializedString);
		return deserializeGameData(reader);
	}

	public static GameObjectsList deserializeGameData(Reader reader) {
		return deserialize(reader, GameObjectsList.class);
	}

	public static <T> T deserialize(Reader reader, Class<T> clazz) {
		try {
			JAXBContext context = JAXBContext.newInstance(clazz);
			Unmarshaller unmarshaller = context.createUnmarshaller();
			return (T) unmarshaller.unmarshal(reader);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}
}
